#include "TcpServer.hpp"
#include "Protocol.hpp"
#include <string>
#include <memory>
#include "Demon.hpp"

using namespace nets_tcpserver;
using namespace ns_protocol;
void Usage(const std::string &proc)
{
    std::cout << "\nUsage: " << proc << " port\n"
              << std::endl;
}

static Response calculatorHelper(const Request &req)
{
    Response resq(0, 0);
    switch (req._op)
    {
    case '+':
        resq._result = req._x + req._y;
        break;
    case '-':
        resq._result = req._x - req._y;
        break;
    case '*':
        resq._result = req._x * req._y;
        break;
    case '/':
        if (req._y == 0)
        {
            resq._code = 1;
        }
        else
            resq._result = req._x / req._y;
        break;
    case '%':
        if (req._y == 0)
        {
            resq._code = 2;
        }
        else
            resq._result = req._x % req._y;
        break;
    default:
        resq._code = 3;
        break;
    }
    return resq;
}

void calculator(int sock)
{
    std::string inbuffer;
    while (true)
    {
        bool red = Recv(sock, &inbuffer);
        if (!red)
            break;

        // 协议解析，保证得到一个完整的报文
        // std::cout<<"begin inbuffer:" << inbuffer << std::endl;
        std::string package = Decond(inbuffer);
        if (package.empty())
            continue;
        // std::cout<<"end inbuffer:" << inbuffer << std::endl;
        // std::cout<<"package:" << package << std::endl;
        logMessage(NORMAL, "%s", package.c_str());
        // 保证是一个完整的报文
        Request req;
        //反序列化，字节流-》结构化
        req.Deserialize(package); // 反序列化
        //业务逻辑
        Response resp = calculatorHelper(req);
        // 序列化
        std::string respString = resp.Serialize(); 
        // std::cout<<"begin respString:" << respString << std::endl;
        respString = Encode(respString);
        // std::cout<<"end respString:" << respString << std::endl;
        //Send我们暂时就这样写，后面再修改，目前send是有问题的
        Send(sock, respString);
    }
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(-1);
    }
    // 在写server时，要有严谨的判断逻辑
    // 一般服务器都要进行忽略SIGPIPE，，防止在运行中出现非法写入的问题
    signal(SIGPIPE, SIG_IGN);
    demon();
    std::unique_ptr<TcpServer> server(new TcpServer(atoi(argv[1])));
    server->BindServer(calculator);
    server->Start();

    // 测试序列化和反序列化
    //  Request req(21,43,'+');
    //  std::string s = req.Serialize();
    //  std::cout << s << std::endl;

    // Request temp;
    // temp.Deserialize(s);
    // std::cout << temp._x << std::endl;
    // std::cout << temp._y << std::endl;
    // std::cout << temp._op << std::endl;

    return 0;
}